#include "SimDongle.h"
#include <wiringPi.h>
#include <wiringSerial.h>
#include <iostream>
#include <vector>
#include <thread>
#include <cjson/cJSON.h>
#include <unistd.h>

using std::cout;
using std::cin;
using std::endl;
using std::cerr;


std::vector<std::string> splitATRaw(const std::string& input, const std::string& pattern)
{
	std::vector<string> resVec;

	if ("" == input)
	{
		return resVec;
	}
	string str = input;
	size_t pos = str.find(pattern);

	while (pos != string::npos)
	{
		string x = str.substr(0, pos);
		if ("" != x)
			resVec.push_back(x);
		str = str.substr(pos + pattern.length(), str.size());
		pos = str.find(pattern);
	}
	if(str.size())
		resVec.push_back(str);
	return resVec;
}



SimDongle::SimDongle() : buffer(0, SIM_DONGLE_DB_NAME, SIM_DONGLE_CONFIG_TABLE_NAME, SIM_DONGLE_DATA_TABLE_NAME)
{
	usbFd = serialOpen(SIMDONGLE_USB_DEVICE, SIMDONGLE_USB_BAUD);
	if (-1 == usbFd)
		cerr << "SimDongle::ERROR::OPEN_SERIAL\n";
	configure();
}

SimDongle::~SimDongle()
{
	if (-1 != usbFd)serialClose(usbFd);
}

int SimDongle::getGPSInfo(GPSInfo & resGpsInfo)
{
	serialFlush(usbFd);
	char ATCmd[] = AT_GPS_INFO;

	int n = write(usbFd, ATCmd, sizeof(ATCmd));
	char raw[256]{ 0 };
	int i = 0;
	//cout << "write :" << n << " bytes.\n";
	delay(100);
	while (serialDataAvail(usbFd) > 0)
	{
		raw[i++] = serialGetchar(usbFd);
	}
	string data(raw);
	std::vector<string> res =  splitATRaw(data, "\r\n");
	string resInfo = res[1];
	const string INFO_HEADER = "+CGPSINFO: ";
	resInfo.replace(resInfo.find(INFO_HEADER), INFO_HEADER.length(), "");
	std::vector<string> gpsInfoVec = splitATRaw(resInfo, ",");

	//GPSInfo resGpsInfo;
	if (gpsInfoVec.empty())
	{
		return -1;
	}
	
	resGpsInfo.lantitude = gpsInfoVec[0] + gpsInfoVec[1];
	resGpsInfo.longitude = gpsInfoVec[2] + gpsInfoVec[3];
	resGpsInfo.date = gpsInfoVec[4];
	resGpsInfo.utc_time = gpsInfoVec[5];
	resGpsInfo.alt = gpsInfoVec[6];
	resGpsInfo.speed = gpsInfoVec[7];

	return 0;
}

void SimDongle::recordData(const GPSInfo & gpsInfo)
{
	cJSON* gpsInfoObj = cJSON_CreateObject();
	cJSON* lantitude = cJSON_CreateString(gpsInfo.lantitude.c_str());
	cJSON* longitude = cJSON_CreateString(gpsInfo.longitude.c_str());
	cJSON* date = cJSON_CreateString(gpsInfo.date.c_str());
	cJSON* utc_time = cJSON_CreateString(gpsInfo.utc_time.c_str());
	cJSON* alt = cJSON_CreateString(gpsInfo.alt.c_str());
	cJSON* speed = cJSON_CreateString(gpsInfo.speed.c_str());

	cJSON_AddItemToObject(gpsInfoObj, "lantitude", lantitude);
	cJSON_AddItemToObject(gpsInfoObj, "longitude", longitude);
	cJSON_AddItemToObject(gpsInfoObj, "date", date);
	cJSON_AddItemToObject(gpsInfoObj, "utc_time", utc_time);
	cJSON_AddItemToObject(gpsInfoObj, "alt", alt);
	cJSON_AddItemToObject(gpsInfoObj, "speed", speed);

	buffer.writeDataJsonToBuffer(cJSON_Print(gpsInfoObj));

	cJSON_free(gpsInfoObj);
	cJSON_free(lantitude);
	cJSON_free(longitude);
	cJSON_free(date);
	cJSON_free(utc_time);
	cJSON_free(alt);
	cJSON_free(speed);
}

void SimDongle::configure()
{
	string configJson;
	Config config;

	if (buffer.readConfigJsonFromBuffer(configJson))
	{
		//读取配置失败
		config.setSample(1);
		cerr << "读取失败使用默认配置: sample = 1\n";
		writeConfig(config);
	}
	else
	{
		cJSON* configJsonObj = cJSON_Parse(configJson.c_str());
		cJSON* sample = cJSON_GetObjectItemCaseSensitive(configJsonObj, "sample");
		if (sample)
		{
			config.setSample(sample->valueint);
			cJSON_free(configJsonObj);
			cJSON_free(sample);
		}
	}
}

void SimDongle::writeConfig(const Config& config) const
{
	cJSON* configObj = cJSON_CreateObject();
	cJSON* sample = cJSON_CreateNumber(config.getSample());
	cJSON_AddItemToObject(configObj, "sample", sample);

	this->buffer.writeConfigJsonToBuffer(cJSON_Print(configObj));

	cJSON_free(configObj);
	cJSON_free(sample);
}

void SimDongle::run()
{
}
